/*
 * ====================================================
 * Copyright (C) 2007 by Ellips BV. All rights reserved.
 *
 * Permission to use, copy, modify, and distribute this
 * software is freely granted, provided that this notice
 * is preserved.
 * ====================================================
 */

  #include "x86_64mach.h"

  .global SYM (memset)
  SOTYPE_FUNCTION(memset)

 /*
  * Avoid revealing the sandbox base address. In particular, we never read from
  * r11, and avoid using the string instructions (stos) because they leave the
  * full 64 bits in rdi.
  */

SYM (memset):
  movl    edi, r9d                /* Save return value */
  movl    esi, eax
  movl    edx, ecx
  cmpl    $16, edx
  jb      .Lbyte_set

  movl    edi, r8d                /* Align on quad word boundary */
  andl    $7, r8d
  jz      .Lquadword_aligned
  movl    $8, ecx
  subl    r8d, ecx
  subl    ecx, edx
.Lheader_loop:
  movb    al, %nacl:(r15, rdi)
  inc     edi
  dec     ecx
  jnz     .Lheader_loop

  movl    edx, ecx

.Lquadword_aligned:
  movabs  $0x0101010101010101, r8
  movzbl  sil, eax
  imul    r8, rax
  cmpl    $256, edx
  jb      .Lquadword_set

  shrl    $7, ecx                 /* Store 128 bytes at a time */

  /* Save the frame pointer and use it as a base to avoid repeated masking */
  pushq   $0
  movl    ebp, (rsp)
  naclrestbp edi, r15

  .p2align 4
.Lquadword_aligned_loop:

  movq    rax,     (rbp)
  movq    rax, 8   (rbp)
  movq    rax, 16  (rbp)
  movq    rax, 24  (rbp)
  movq    rax, 32  (rbp)
  movq    rax, 40  (rbp)
  movq    rax, 48  (rbp)
  movq    rax, 56  (rbp)
  movq    rax, 64  (rbp)
  movq    rax, 72  (rbp)
  movq    rax, 80  (rbp)
  movq    rax, 88  (rbp)
  movq    rax, 96  (rbp)
  movq    rax, 104 (rbp)
  movq    rax, 112 (rbp)
  movq    rax, 120 (rbp)

  .bundle_lock
  leal    128 (rbp), ebp
  add     r15, rbp
  .bundle_unlock

  dec     ecx
  jnz     .Lquadword_aligned_loop

  movl    ebp, edi
  popq    r8
  naclrestbp r8d, r15

  movl    edx, ecx
  andl    $127, ecx
  jz      .Lfooter_loop_end
.Lfooter_loop:
  movb    al, %nacl:(r15, rdi)
  inc     edi
  dec     ecx
  jnz      .Lfooter_loop
.Lfooter_loop_end:
  movl    r9d, eax
  pop     r11
  nacljmp r11d, r15


.Lbyte_set:
  testl   ecx, ecx
  jz      .Lbyte_set_end
.Lbyte_set_loop:
  movb    al, %nacl:(r15, rdi)
  inc     edi
  dec     ecx
  jnz     .Lbyte_set_loop
.Lbyte_set_end:
  movl    r9d, eax
  pop     r11
  nacljmp r11d, r15


.Lquadword_set:
  shrl    $3, ecx
  jz      .Lquadword_loop_end
  .p2align 4
.Lquadword_loop:
  movq    rax, %nacl:(r15, rdi)
  add     $8, edi
  dec     ecx
  jnz     .Lquadword_loop
.Lquadword_loop_end:
  movl    edx, ecx
  andl    $7, ecx
  jz      .Lquadword_footer_end
.Lquadword_footer:
  movb    al, %nacl:(r15, rdi)
  inc     edi
  dec     ecx
  jnz     .Lquadword_footer
.Lquadword_footer_end:
  movl    r9d, eax
  pop     r11
  nacljmp r11d, r15

